package com.lcf.common.util;

import cn.hutool.core.lang.Console;
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import com.drew.metadata.exif.ExifIFD0Directory;
import com.drew.metadata.exif.ExifSubIFDDirectory;
import com.drew.metadata.exif.GpsDirectory;
import com.drew.metadata.file.FileTypeDirectory;
import com.lcf.common.model.MetadataBo;
import lombok.Data;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <a href="https://drewnoakes.com/code/exif/index.html">drewnoakes</a>
 */
public class MetadataUtils {

    private static final Map<Type, Map<Integer, String>> EXPLAIN_MAP = new HashMap<>();

    @Data
    public static class Type {
        private Class clazz;
        private String name;

        public Type(Class clazz, String name) {
            this.clazz = clazz;
            this.name = name;
        }
    }

    static {
        // Exif IFD0
        Map<Integer, String> emap = new HashMap<>();
        emap.put(ExifIFD0Directory.TAG_MAKE, "设备制造商");
        emap.put(ExifIFD0Directory.TAG_MODEL, "设备型号");
        emap.put(ExifIFD0Directory.TAG_ORIENTATION, "方向");
        emap.put(ExifIFD0Directory.TAG_X_RESOLUTION, "水平分辨率");
        emap.put(ExifIFD0Directory.TAG_Y_RESOLUTION, "垂直分辨率");
        emap.put(ExifIFD0Directory.TAG_RESOLUTION_UNIT, "分辨率单位");
        emap.put(ExifIFD0Directory.TAG_SOFTWARE, "软件信息");
        emap.put(ExifIFD0Directory.TAG_DATETIME, "时间");
        EXPLAIN_MAP.put(new Type(ExifIFD0Directory.class, "Exif IFD0"), emap);
        // Exif SubIFD
        Map<Integer, String> esmap = new HashMap<>();
        esmap.put(ExifSubIFDDirectory.TAG_FNUMBER, "光圈");
        esmap.put(ExifSubIFDDirectory.TAG_EXPOSURE_TIME, "曝光时间");
        esmap.put(ExifSubIFDDirectory.TAG_FOCAL_LENGTH, "焦距长度");
        esmap.put(ExifSubIFDDirectory.TAG_FLASH, "闪光");
        esmap.put(ExifSubIFDDirectory.TAG_METERING_MODE, "曝光的测光方法");
        esmap.put(ExifSubIFDDirectory.TAG_ISO_EQUIVALENT, "感光度");
        esmap.put(ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED, "数字化时间");
        esmap.put(ExifSubIFDDirectory.TAG_EXPOSURE_BIAS, "曝光补偿");
        esmap.put(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL, "拍摄时间");
        esmap.put(ExifSubIFDDirectory.TAG_EXIF_IMAGE_HEIGHT, "高度");
        esmap.put(ExifSubIFDDirectory.TAG_EXIF_IMAGE_WIDTH, "宽度");
        EXPLAIN_MAP.put(new Type(ExifSubIFDDirectory.class, "Exif SubIFD"), esmap);
        // GPS
        Map<Integer, String> gpsmap = new HashMap<>();
        gpsmap.put(GpsDirectory.TAG_LATITUDE, "GPS纬度");
        gpsmap.put(GpsDirectory.TAG_LATITUDE_REF, "GPS纬度参考");
        gpsmap.put(GpsDirectory.TAG_LONGITUDE, "GPS经度");
        gpsmap.put(GpsDirectory.TAG_LONGITUDE_REF, "GPS经度参考");
        gpsmap.put(GpsDirectory.TAG_TIME_STAMP, "GPS Time-Stamp");
        gpsmap.put(GpsDirectory.TAG_DATE_STAMP, "GPS Date Stamp");
        EXPLAIN_MAP.put(new Type(GpsDirectory.class, "GPS"), gpsmap);
        // File Type
        Map<Integer, String> fileTypeMap = new HashMap<>();
        fileTypeMap.put(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE, "MIME类型");
        fileTypeMap.put(FileTypeDirectory.TAG_EXPECTED_FILE_NAME_EXTENSION, "文件扩展名");
        fileTypeMap.put(FileTypeDirectory.TAG_DETECTED_FILE_TYPE_NAME, "文件类型名称");
        EXPLAIN_MAP.put(new Type(FileTypeDirectory.class, "File Type"), fileTypeMap);
    }

    public static List<MetadataBo> getMetadata(InputStream inputStream)
            throws ImageProcessingException, IOException {
        Metadata metadata = ImageMetadataReader.readMetadata(inputStream);
        return getMetadata(metadata);
    }

    public static List<MetadataBo> getMetadata(File file)
            throws ImageProcessingException, IOException {
        Metadata metadata = ImageMetadataReader.readMetadata(file);
        return getMetadata(metadata);
    }

    public static List<MetadataBo> getMetadata(Metadata metadata) {
        List<MetadataBo> metadataBoList = new ArrayList<>();
        EXPLAIN_MAP.forEach((k, v) -> {
            Directory directory = metadata.getFirstDirectoryOfType(k.clazz);
            Map<String, Tag> tagMap;
            if (directory != null) {
                tagMap = directory.getTags().stream().collect(Collectors.toMap(Tag::getTagTypeHex, Function.identity()));
            } else {
                tagMap = new HashMap<>();
            }
            Map<Integer, String> dmap = EXPLAIN_MAP.get(k);
            //
            List<MetadataBo.Info> infoList = new ArrayList<>();
            dmap.forEach((k1, v1) -> {
                Tag tag = tagMap.get(String.format("0x%04x", k1));
                MetadataBo.Info add;
                if (tag != null) {
                    add = new MetadataBo.Info(String.format("0x%04x", k1), tag.getTagName(), v1, tag.getDescription());
                } else {
                    add = new MetadataBo.Info(String.format("0x%04x", k1), "", v1, "");
                }
                infoList.add(add);
            });
            metadataBoList.add(new MetadataBo(k.getName(), infoList));
        });
        return metadataBoList;
    }

    /**
     * https://www.freesion.com/article/9105899809/
     *
     * @param args
     * @throws IOException
     * @throws ImageProcessingException
     */
    public static void main(String[] args) throws IOException, ImageProcessingException {

        System.out.println("*************************** 照片基础信息 ***********************************");

        File imageFile = new File("C:\\Users\\Administrator\\Desktop\\声像测试数据\\005、信息化和信息系统2.MP3");
        //Console.log(JSONUtil.toJsonStr(getMetadata(imageFile)));
        console(ImageMetadataReader.readMetadata(imageFile));

        System.out.println("*************************** 视频基础信息 ***********************************");
        //Console.log(JSONUtil.toJsonStr(getMetadata(Files.newInputStream(Paths.
        //        get("C:\\Users\\Administrator\\Documents\\WeChat Files\\wxid_bij0qf56w0ib21\\FileStorage\\Video\\2023-04\\4d1419b87b574ea6c0fb9dfe214b395e.mp4")))));


        /**
         * 1: 未知文件类型
         * Metadata metadata = ImageMetadataReader.readMetadata(file);
         *
         * 2: 特定文件类型
         * Metadata metadata = JpegMetadataReader.readMetadata(file);
         *
         * 3: 特定的元数据类型
         * Iterable<JpegSegmentMetadataReader> readers = Arrays.asList(new ExifReader(), new IptcReader());
         * Metadata metadata = JpegMetadataReader.readMetadata(file, readers);
         *
         */

    }

    private static void console(Metadata metadata) {
        Console.log("----------------------------------- 原始数据 -----------------------------------");
        metadata.getDirectories().forEach(directory -> {
            Collection<Tag> tags = directory.getTags();
            Console.log(" ====== Directory : {} ======", directory.getName());
            tags.forEach(tag -> {
                Console.log("tagTypeHex: {} , tagName : {} , tagDesc : [{}]", tag.getTagTypeHex(), tag.getTagName(), tag.getDescription());
            });
        });
    }

}
